#!/usr/bin/env python 
# -*- coding: utf-8 -*-
# @Time    : 2023/4/14 13:46
# @Author  : WJQ
# @Site    : 
# @File    : popup_handler.py.py
# @Software: PyCharm
# modules_wx/popup_handler.py
import re
import time
import traceback

from appium.webdriver.common.appiumby import AppiumBy
from lxml import etree
from selenium.common.exceptions import TimeoutException, NoSuchElementException, WebDriverException


import conf
from browser.driver_wx import DriverHandlerWx
from browser.page import PageHandler
from crawler.modules.click_handler import ClickHandler
from crawler.modules_native.instrument import capture_screenshot
from utils.common import CrawlerLogger

class PopupHandler:
    def __init__(self, driver_handler):
        self.driver_handler: DriverHandlerWx = driver_handler

    def handle_native_popups ( self) :
        self.driver_handler.switch_to_native_app_context()
        try:
            for id in conf.CLIENT_SIDE_CONF.POP_UPS_ID:
                pop_ups = PageHandler.safe_find_element(self.driver_handler.driver, AppiumBy.ID, id, timeout=0.5)
                if pop_ups :
                    CrawlerLogger.info(f"[+] 关闭弹窗: {pop_ups.text}")
                    if "跳转" in pop_ups.text or "打开" in pop_ups.text:
                        PageHandler.safe_click_element(self.driver_handler.driver, AppiumBy.ID,
                                            conf.CLIENT_SIDE_CONF.POP_UPS_ID[id][0])
                    else:
                        capture_screenshot(self.driver_handler.driver, "permission",
                                           self.driver_handler.applets_name)
                        PageHandler.safe_click_element(self.driver_handler.driver, AppiumBy.ID,
                                            conf.CLIENT_SIDE_CONF.POP_UPS_ID[id][1])
        except Exception as e:
            CrawlerLogger.error(f"[-] {traceback.format_exc()}")
            CrawlerLogger.error(f"[-] Error in run: {e}")

    def handle_webview_popups( self ):
        if conf.WEBVIEW_MODE :
            self.driver_handler.switch_to_webview_context()
            # 构建 XPath 表达式
            if PageHandler.safe_find_element_visible(self.driver_handler.driver, AppiumBy.XPATH, "//*[contains(normalize-space(text()), '隐私政策')]"):
                capture_screenshot(self.driver_handler.driver, "privacy_policy", self.driver_handler.applets_name)
                CrawlerLogger.info("[+] 出现隐私政策")
            xpath_conditions = [
                f"contains(normalize-space(text()), '{keyword}')"
                for keyword in conf.CLIENT_SIDE_CONF.POP_TEXT_KEYWORD
            ]
            xpath_expression = f"//{conf.CLIENT_SIDE_CONF.PLATFORM}-button[{' or '.join(xpath_conditions)}]"
            PageHandler.safe_click_elements(self.driver_handler.driver, AppiumBy.XPATH, xpath_expression)
        else:
            self.driver_handler.switch_to_native_app_context()
            if PageHandler.safe_find_elements(self.driver_handler.driver, AppiumBy.XPATH, "//*[contains(@text, '隐私政策')]"):
                capture_screenshot(self.driver_handler.driver, "privacy_policy", self.driver_handler.applets_name)
                CrawlerLogger.info("[+] 出现隐私政策")
            xpath_conditions = [
                f"contains(@text, '{keyword}')"
                for keyword in conf.CLIENT_SIDE_CONF.POP_TEXT_KEYWORD
            ]
            xpath_conditions = f"//android.view.View[{' or '.join(xpath_conditions)}]"
            PageHandler.safe_click_elements(self.driver_handler.driver, AppiumBy.XPATH, xpath_conditions)


    def handle_popups(self):
        page_source = self.driver_handler.driver.page_source
        root = etree.fromstring(page_source.encode('utf-8'))
        webview = root.find(".//android.webkit.WebView")

        if webview is not None:
            views = webview.findall(".//android.view.View")

            # Parse bounds and find elements which cover others
            overlapped_elements = self.find_overlapping_elements(views)

            for element in overlapped_elements:
                self.dismiss_popup(element)

    def parse_bounds(self, bounds_str):
        match = re.match(r'\[(\d+),(\d+)]\[(\d+),(\d+)]', bounds_str)
        if match:
            return list(map(int, match.groups()))
        else:
            raise ValueError(f"Couldn't parse bounds: {bounds_str}")

    def find_overlapping_elements(self, views):
        overlapped_elements = []
        for i in range(len(views)):
            bounds_i = self.parse_bounds(views[i].get('bounds'))
            for j in range(i+1, len(views)):
                bounds_j = self.parse_bounds(views[j].get('bounds'))
                if self.is_overlap(bounds_i, bounds_j):
                    overlapped_elements.append(views[j])
        return overlapped_elements

    def is_overlap(self, bounds1, bounds2):
        x1, y1, x2, y2 = bounds1
        x3, y3, x4, y4 = bounds2
        return not (x2 < x3 or x1 > x4 or y2 < y3 or y1 > y4)

    def dismiss_popup(self, view):
        xpath = ".//*[@text='确定' or @text='×' or @text='同意']"
        while True:
            try:
                # update page source
                page_source = self.driver_handler.driver.page_source
                root = etree.fromstring(page_source.encode('utf-8'))
                element = root.xpath(xpath)
                if element:
                    PageHandler.safe_find_element(self.driver_handler.driver, AppiumBy.XPATH, xpath).click()
                else:
                    break
            except (TimeoutException, NoSuchElementException, WebDriverException):
                break


    def handle_popups2(self):

        while True:
            # 处理webview弹窗
            self.driver_handler.switch_to_webview_context()
            webview_popup = self.find_webview_popup()
            if webview_popup:
                CrawlerLogger.info(f"[+] Webview弹窗已找到")
                agree_xpath = '//wx-button[' + ' or '.join(
                    f'contains(text(), "{text}")' for text in conf.SELECTION_CONF.POP_TEXT_KEYWORD) + ']'
                agree_btn = PageHandler.safe_find_element(self.driver_handler.driver, AppiumBy.XPATH, agree_xpath)

                close_css_selector = 'wx-view[class*="close"]'
                close_btn = PageHandler.safe_find_element(self.driver_handler.driver, AppiumBy.CSS_SELECTOR,
                                                          close_css_selector)

                if agree_btn or close_btn:
                    if agree_btn:
                        ClickHandler.safe_click(self.driver_handler.driver, agree_btn, self.driver_handler.driver.title)
                    if close_btn:
                        ClickHandler.safe_click(self.driver_handler.driver, close_btn, self.driver_handler.driver.title)
                    CrawlerLogger.info(f"[+] Webview弹窗已处理")
                    time.sleep(1)
                    continue

            self.driver_handler.switch_to_native_app_context()
            for resource_id in conf.SELECTION_CONF.NATIVE_POP_RESOURCE_ID:
                # 处理native弹窗
                native_popup = PageHandler.safe_find_element(self.driver_handler.driver, AppiumBy.ID, resource_id)
                if native_popup:
                    CrawlerLogger.info(f"[+] Native弹窗已找到")
                    for id in conf.SELECTION_CONF.POP_UPS_ID:
                        close_btn = PageHandler.safe_find_element(self.driver_handler.driver, AppiumBy.ID, id)
                        if close_btn:
                            ClickHandler.safe_click(self.driver_handler.driver, close_btn, 'Native APP')
                            CrawlerLogger.info(f"[+] Native弹窗已处理")
                            time.sleep(1)
                            continue

            # 如果没有找到弹窗，退出循环
            break

    def find_webview_popup(self):
        '''
        查找webview弹窗 z-index
        :return:
        '''
        # TODO 优化查找webview弹窗的方法
        webview_popup_css_selector = 'wx-view'
        webview_popup = self.driver_handler.driver.find_elements(AppiumBy.CSS_SELECTOR, webview_popup_css_selector)[::-1]

        popup_element = None

        for view in webview_popup:
            z_index = view.value_of_css_property("z-index")
            try:
                if z_index and int(z_index) > 0:
                    popup_element = view
                    break
            except ValueError:
                # 忽略无法转换为整数的z-index值，例如'auto'
                pass
        return popup_element

    def click_necessary_button(self):
        buttons = PageHandler.safe_find_elements(self.driver_handler.driver, AppiumBy.XPATH, '//*[contains(@text, "更多")]')
        if buttons:
            for button in buttons:
                button.click()
